home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / tex / src / flib / flib.c next >
C/C++ Source or Header  |  1992-11-04  |  47KB  |  1,874 lines

  1. /*
  2.  *    Fontlibrary program.
  3.  *
  4.  *        used for our TeX-system to save disk space and for
  5.  *        speed up the loading of fonts for "ShowDVI" and "DVIprint".
  6.  *
  7.  *    This program is freely redistributable. You may modify and use this
  8.  *    program to your heart's content, so long as you send modifications
  9.  *    to Georg Hessmann. It can be included in any distribution, commercial
  10.  *    or otherwise, so long as the banner string defined in the constant
  11.  *    HEADER is not modified (except for the version number and the machine
  12.  *    type) and this banner is printed on program invocation, or can be
  13.  *    printed on program invocation with the -? option.
  14.  *
  15.  *    For further information read the README file.
  16.  *
  17.  *      31.01.90  (hes)      (C) Copyright 1990/91 Georg Hessmann.
  18.  *
  19.  *      12.02.90  (hes) v1.01    new flib-format, rename command
  20.  *      14.02.90  (rbs)        ported to Atari ST
  21.  *      25.04.90  (jrb)        fixed up for Atari ST gcc
  22.  *    05.06.90  (hes) v1.02    little bug fixes, add flib links (hes)
  23.  *    08.01.91  (hes) v1.03    add relative flib links
  24.  *      03.11.92  (hes) v1.10   add wildcard support (only with Dice/Amiga)
  25.  *                add two new flags 's' and 'e'
  26.  *                's' -- strip path, don't store the path of a font
  27.  *                'e' -- strip extension, don't store the extension
  28.  */
  29.  
  30.  
  31. /* Is the compiler a ANSI-C compiler */
  32. #ifdef AMIGA
  33. #  ifdef LATTICE
  34. #    define ANSI
  35. #  endif
  36. #  ifdef AZTEC_C
  37. #    define ANSI
  38. #  endif /* AZTEC_C */
  39. #  ifdef _DCC
  40. #    define ANSI
  41. #  endif /* _DCC */
  42. #else
  43. #  ifdef ATARI
  44. #    ifdef __GNUC__
  45. #      define ANSI
  46. #    endif /* __GNUC__ */
  47. #  endif /* ATARI */
  48. #endif /* AMIGA */
  49.  
  50. /* standard includes */
  51. #include <stdio.h>
  52. #ifdef ANSI
  53. #  include <stdlib.h>
  54. #  include <string.h>
  55. #  ifdef AMIGA
  56. #    ifndef _DCC
  57. #      include <dos.h>
  58. #    endif /* !_DCC */
  59. #  endif /* AMIGA */
  60. #  ifdef ATARI
  61. #    ifndef __GNUC__
  62. #        include <tos.h>
  63. #        include <ext.h>
  64. #    else
  65. #        include <unixlib.h>
  66. #        include <fcntl.h>
  67. #        define S_IWRITE    W_OK
  68. #        define S_IREAD     R_OK
  69. #    endif /* __GNUC__ */
  70. #  endif /* ATARI */
  71. #endif /* ANSI */
  72.  
  73.  
  74.  
  75. /* open mode for files */
  76. #ifdef ATARI
  77. #  define OPEN_FOR_READING "rb"
  78. #  define OPEN_FOR_WRITING "wb"
  79. #  define OPEN_FOR_APPEND  "rb+"
  80. #  ifndef __GNUC__
  81.      extern int access(char *, int);
  82. #  endif /* __GNUC__ */
  83. #else
  84. #  define OPEN_FOR_READING "r"
  85. #  define OPEN_FOR_WRITING "w"
  86. #  define OPEN_FOR_APPEND  "r+"
  87. #endif
  88.  
  89. /* prototyping on/off */
  90. #ifdef ANSI
  91. #  define Args(x)    x
  92. #else
  93. #  define Args(x)    ()
  94. #endif /* ANSI */
  95.  
  96.  
  97. #ifdef AZTEC_C
  98.    void *malloc        Args((unsigned));
  99.    void free        Args((char *));
  100.    char *strchr();
  101.    char *strrchr();
  102. #endif /* AZTEC_C */
  103.  
  104.  
  105. #ifdef AMIGA
  106. #  ifdef LATTICE
  107. #    define perror(x)    poserr(x)
  108. #  endif /* LATTICE */
  109. #  ifdef AZTEC_C
  110. #    define remove(x)    unlink(x)
  111.      /* warning: AztecC seems to have problems with the returncode from fseek */
  112. #  endif /* AZTEC_C */
  113. #else AMIGA
  114. #  ifndef ANSI
  115. #    define remove(x)    unlink(x)
  116. #  endif /* ANSI */
  117. #endif /* AMIGA */
  118.  
  119. #ifdef ATARI
  120. #  include <errno.h>
  121. #else
  122. extern int errno;
  123. #endif
  124.  
  125. /*    Aufbau einer Fontlibrary :
  126.  *    +---------------------------------------+
  127.  *    |   magic number        4 Bytes    |
  128.  *    |   number of direntries    4 Bytes    |
  129.  *    |   [flib_dirent]*            |
  130.  *    |   [modules]*                |
  131.  *    +---------------------------------------+
  132.  */
  133.  
  134.  
  135.  
  136. /* important constants */
  137. #define OLD_LIBMAGIC    0xA797F033L        /* magic number */
  138. #define LIBMAGIC    (((long)'F'<<24) | ((long)'L'<<16) | ((long)'I'<<8) | (long)'B')
  139. #define LNKMAGIC    (((long)'F'<<24) | ((long)'L'<<16) | ((long)'N'<<8) | (long)'K')
  140. #define FILENAMELEN    14
  141. #define NEWFILENAMELEN    22
  142. #define TMPFLIB        "tmpflib.tmp"
  143. #define BUFSIZE        20480
  144. #define DOSNAMESIZE    100
  145. #define MAXLINKLEVELS    20
  146.  
  147. #ifdef AMIGA
  148. #  define MACHINE    "AMIGA"
  149. #else
  150. #  ifdef ATARI
  151. #    define MACHINE    "ATARI"
  152. #  else
  153. #    define MACHINE    "UNIX"
  154. #    include <sys/file.h>
  155. #    define S_IWRITE    W_OK
  156. #    define S_IREAD    R_OK
  157. #  endif /* ATARI */
  158. #endif /* AMIGA */
  159.  
  160. #define VERSION        "1.10"
  161. #ifdef ATARI
  162. #  define HEADER        "FontLib Manager - Version %s for %s \275 1990/91/92 Georg Hessmann/Robert Stabl\n"
  163. #else
  164. #  define HEADER        "FontLib Manager - Version %s for %s (c) 1990/91/92 Georg Hessmann\n"
  165. #endif
  166.  
  167. #ifdef AMIGA
  168. static char version[] = "\0$VER: flib 1.10 (11/03/92)";
  169. #endif
  170.  
  171.  
  172. #define    OLD_VERSION    0
  173. #define NEW_VERSION    1
  174.  
  175.  
  176. static char buffer[BUFSIZE];    /* used to copy modules */
  177.  
  178.  
  179. #ifndef FALSE
  180. #  define FALSE        0
  181. #endif /* FALSE */
  182. #ifndef TRUE
  183. #  define TRUE        (!FALSE)
  184. #endif /* TRUE */
  185.  
  186. #define offset(ptr,member)    ((long)(&((ptr)->member))-(long)(ptr))
  187.  
  188.  
  189. /************ structure definitions ***************/
  190. /* fontlib directory structures */
  191. struct flib_dirent { char mname[FILENAMELEN];        /* old version */
  192.                      long size;        /* size of pk-module in bytes */
  193.                      long where;    /* position in flib-file */
  194.                    };
  195.  
  196. struct new_flib_dirent { char  mname[NEWFILENAMELEN];    /* new version */
  197.              unsigned short checksum;
  198.              long  size;        /* size of pk-module in bytes */
  199.              long  where;        /* position in flib-file */
  200.              char * real_path;    /* only for flib internal use!! */
  201.                          /* real_path won't saved to the flib */
  202.                        };
  203.  
  204. union direntry { struct flib_dirent    old;
  205.          struct new_flib_dirent    new;
  206.            };
  207.  
  208.  
  209. /* internal representation of the flib-directory */
  210. struct dirlist { struct new_flib_dirent dirent;
  211.                  struct dirlist *next;
  212.            };
  213.  
  214. struct dir { long        total;
  215.          long        alloc;
  216.          int        version;    /* old or new flib */
  217.          int        is_link;
  218.              struct dirlist *dirlist;
  219.              char        real_name[DOSNAMESIZE];
  220.        };
  221.  
  222.  
  223. /*********   P R O T O T Y P E S   ********/
  224.  
  225.     /* main function                        */
  226. void main                Args((int argc, char *argv[]));
  227.  
  228.  
  229. /********* local functions **********/
  230.     /* print the help                        */
  231. static void  usage            Args((char *pname));
  232.     /* parse the first argument                    */
  233. static int   decode_args        Args((int argc, char **argv,
  234.                           int *table,
  235.                           int *extract,
  236.                           int *create,
  237.                           int *delete,
  238.                           int *compress,
  239.                           int *verbose,
  240.                           int *rename,
  241.                           int *test,
  242.                           int *link,
  243.                           int *term_input));
  244.  
  245.  
  246.     /* calculates the length of a module name */
  247. static int   module_len(char * name);
  248.  
  249.     /* delete flib with the name "name" and rename the tmpflib to "name" */
  250.     /* nr is the number of modules in the flib => nr == 0 --> no flib    */
  251. static int   insert_name_into_dir    Args((char *name,
  252.                           struct dirlist **dirl,
  253.                           int version));
  254.     /* is module from "test" in "inp1" or "inp2" ? */
  255. static struct dirlist *exist_entry    Args((struct dirlist *inp1,
  256.                           struct dirlist *inp2,
  257.                           struct dirlist *test));
  258.     /* create a dirlist structure entry whith the module-name "name"    */
  259. static int   read_new_modules        Args((int term_input,
  260.                           int argc,
  261.                           char **argv,
  262.                           struct dir *directory,
  263.                           struct dirlist **start_dirl,
  264.                           int verbose));
  265.     /* read a list of modules from argv or from stdin        */
  266. static FILE *open_flib            Args((char *name,
  267.                           char *mode,
  268.                           struct dir *directory,
  269.                           short levels));
  270.     /* open a flib and test the magic-number            */
  271. static int   read_dir            Args((FILE *f,
  272.                           struct dir *directory));
  273.     /* read the directory from the flib (file-pointer must be on the first dir)       */
  274.     /* only this directory entries a correct where "where != 0" the others are unused */
  275. static void  print_dir            Args((struct dir *directory,
  276.                           char *lib_name,
  277.                           int verbose));
  278.     /* print the contents of the directory                */
  279. static int   ex_module            Args((struct dir *directory,
  280.                           char *mname,
  281.                           FILE *flib, int verbose));
  282.     /* search a module in the flib and copy it to a new file    */
  283. static int   create_new_flib        Args((struct dir *directory,
  284.                           char *name,
  285.                           int verbose));
  286.     /* create a complete (new) flib, copy only files into the flib    */
  287. static int   copy_module        Args((char *name,
  288.                           char *real_path,
  289.                           FILE *flib,
  290.                           long *size,
  291.                           long *where,
  292.                           unsigned short *check));
  293.     /* create a new flib and prepare the directory part        */
  294. static FILE *copy_directory        Args((struct dir *directory,
  295.                           char *name,
  296.                           int verbose));
  297.     /* copy a module (file) to the actual position in flib        */
  298. static FILE *copy_old_flib        Args((struct dir *directory,
  299.                           FILE *flib,
  300.                           char *name,
  301.                           int verbose));
  302.     /* copy the modules (from flib) with "where != 0" to flib (tmplib) */
  303. static int   append_modules_to_flib    Args((struct dir *directory,
  304.                           FILE *flib,
  305.                           int verbose));
  306.     /* copy the modules (files) with "where == 0" to flib (tmplib)     */
  307. static int   del_module_from_dir    Args((struct dir *directory,
  308.                           char *name,
  309.                           int verbose));
  310.     /* find a module and delete it from the directory list        */
  311. static void  copy_tmpflib        Args((char *name,
  312.                           long nr));
  313.     /* copy file source to file drain                 */
  314. static int   copy_file            Args((char *source,
  315.                           char *drain));
  316.     /* save directory to file                    */
  317. static int   update_dir            Args((struct dir *directory,
  318.                           FILE *flib,
  319.                           int verbose));
  320.  
  321.     /* extract module name from old and copies it to new        */
  322. static void  module_name        Args((char *old, char *new));
  323.  
  324.     /* update ndir.mname according to strip_path and strip_ext    */
  325. static void  upd_font_name        Args((struct new_flib_dirent * ndir));
  326.  
  327.     /* change module-names in directory                */
  328. static int   rename_entries        Args((struct dir *directory,
  329.                           struct dirlist *dirl,
  330.                           int verbose));
  331.     /* test all checksums of the fontlibrary            */
  332. static void  test_flib            Args((FILE *flib,
  333.                           struct dir *directory,
  334.                           int verbose));
  335.     /* read the directory structure                    */
  336. static int   freaddir            Args((union direntry *dir,
  337.                           int version,
  338.                           FILE *f));
  339.     /* read a four byte number <hihi lohi hilo lolo>        */
  340. static int   freadlong            Args((long *buf,
  341.                           FILE *f));
  342.     /* read a two byte number <hi lo>                */
  343. static int   freadshort            Args((unsigned short *buf,
  344.                           FILE *f));
  345.     /* write the directory structure                */
  346. static int   fwritedir            Args((union direntry *dir,
  347.                           int version,
  348.                           FILE *f));
  349.     /* write a four byte number <hihi lohi hilo lolo>        */
  350. static int   fwritelong            Args((long buf,
  351.                           FILE *f));
  352.     /* write a two byte number <hi lo>                */
  353. static int   fwriteshort        Args((unsigned short buf,
  354.                           FILE *f));
  355.  
  356.  
  357.  
  358. /* global variables */
  359. int strip_path, strip_ext;
  360.  
  361.  
  362. /********************   M A I N   ********************/
  363. void main(argc, argv)
  364.   int argc;
  365.   char *argv[];
  366. {
  367.   FILE *flib;
  368.   struct dir directory;
  369.   char input[256];
  370.   int table, extract, create, delete, compress, verbose, rename, test, link, term_input;
  371.   int i;
  372.  
  373.   if (argc < 3) {
  374.     usage(argv[0]);
  375.     exit(5);
  376.   }
  377.  
  378. #ifdef _DCC
  379.   expand_args(argc, argv, &argc, &argv);    /* expand wildcards */
  380. #endif /* _DCC */
  381.  
  382.   directory.total   = directory.alloc = 0;
  383.   directory.dirlist = NULL;
  384.   directory.version = NEW_VERSION;    /* default version */
  385.   flib = NULL;
  386.  
  387.   if (!decode_args(argc, argv, &table, &extract, &create, &delete, &compress,
  388.         &verbose, &rename, &test, &link, &term_input)) {
  389.     usage(argv[0]);
  390.     exit(5);
  391.   }
  392.  
  393.   if (verbose) {
  394.     printf(HEADER,VERSION,MACHINE);
  395.   }
  396.  
  397.   /**************** extract **************/
  398.   if (extract) {
  399.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  400.         exit(5);
  401.     }
  402.     if (!read_dir(flib,&directory)) {
  403.         exit(5);
  404.     }
  405.     if (term_input) {
  406.         while (!feof(stdin)) {
  407.             if (gets(input) != NULL) {
  408.                 (void)ex_module(&directory,input,flib,verbose);
  409.             }
  410.         }
  411.     }
  412.     else {
  413.             if(argc == 3) { /* extract all if no modules specified ++jrb */
  414.             struct dirlist *dl;
  415.             for(dl = directory.dirlist; dl != NULL; dl = dl->next)
  416.             (void)ex_module(&directory,dl->dirent.mname,flib,
  417.                     verbose);
  418.         }
  419.         else { /* extract only modules specified */
  420.             for (i=3; i<argc; i++) {
  421.             (void)ex_module(&directory,argv[i],flib,verbose);
  422.             }
  423.         }
  424.     }
  425.     fclose(flib);
  426.     flib = NULL;
  427.   }
  428.   /**************** create **************/
  429.   if (create) {
  430. #if (defined(ATARI) && (!(defined(__GNUC__)))) || defined(AMIGA)
  431.     if (access(argv[2],6) == 0) {    /* read + write */
  432. #else
  433.     if (access(argv[2],S_IWRITE | S_IREAD) == 0) {    /* read + write */
  434. #endif
  435.         struct dirlist *dirl, *start_dirl;
  436.         FILE *tmplib;
  437.         int nr;
  438.  
  439.         if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  440.             exit(5);
  441.         }
  442.         if (!read_dir(flib,&directory)) {
  443.             exit(5);
  444.         }
  445.         /* nun noch den Rest anhaengen */
  446.         /* internal directory */
  447.         for (dirl = directory.dirlist;
  448.             dirl != NULL && dirl->next != NULL;
  449.             dirl = dirl->next);
  450.         nr = read_new_modules(term_input,argc,argv,
  451.                     &directory,&start_dirl,verbose);
  452.         if (dirl == NULL) {
  453.             directory.dirlist = start_dirl;
  454.             directory.total = nr;
  455.         }
  456.         else {
  457.             dirl->next = start_dirl;
  458.             directory.total += nr;
  459.         }
  460.         directory.alloc += nr;
  461.         /* copy old flib with the new directory */
  462.         if ((tmplib = copy_old_flib(&directory,flib,argv[2],verbose)) == NULL) {
  463.             exit(5);
  464.         }
  465.         /* append the new modules */
  466.         if (!append_modules_to_flib(&directory,tmplib,verbose)) {
  467.             exit(5);
  468.         }
  469.         fclose(tmplib);
  470.         fclose(flib);
  471.         flib = NULL;
  472.         copy_tmpflib(directory.real_name,directory.total);
  473.     }
  474.     else {
  475.         directory.total = read_new_modules(term_input,argc,argv,
  476.                 &directory,&(directory.dirlist),verbose);
  477.         if (!create_new_flib(&directory,argv[2],verbose)) {
  478.             exit(5);
  479.         }
  480.     }
  481.   }
  482.   /**************** delete **************/
  483.   if (delete) {
  484.     FILE *tmplib;
  485.  
  486.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  487.         exit(5);
  488.     }
  489.     if (directory.version == OLD_VERSION) {
  490.         if (verbose) {
  491.             printf("This Option work's only with the new flib-version!\n");
  492.             printf("Convert first the flib with \"flib z %s\"\n",argv[2]);
  493.         }
  494.         else {
  495.             fprintf(stderr,"Wrong flib-version!\n");
  496.         }
  497.     }
  498.     if (!read_dir(flib,&directory)) {
  499.         exit(5);
  500.     }
  501.     if (term_input) {
  502.         while (!feof(stdin)) {
  503.             if (gets(input) != NULL) {
  504.                 (void)del_module_from_dir(&directory,input,verbose);
  505.             }
  506.         }
  507.     }
  508.     else {
  509.         if (argc==3) {
  510.             if (verbose) {
  511.                 printf("No module to delete!?!\n");
  512.             }
  513.             fclose(flib);
  514.             flib = NULL;
  515.             exit(0);
  516.         }
  517.         else {
  518.             for (i=3; i<argc; i++) {
  519.                 (void)del_module_from_dir(&directory,argv[i],verbose);
  520.             }
  521.         }
  522.     }
  523.     /* copy old flib with the new directory */
  524.     if ((tmplib = copy_old_flib(&directory,flib,argv[2],verbose)) == NULL) {
  525.         exit(5);
  526.     }
  527.     /* append the new modules */
  528.     if (!append_modules_to_flib(&directory,tmplib,verbose)) {
  529.         exit(5);
  530.     }
  531.     fclose(tmplib);
  532.     fclose(flib);
  533.     flib = NULL;
  534.     copy_tmpflib(directory.real_name,directory.total);
  535.   }
  536.   /**************** compress **************/
  537.   if (compress) {
  538.     FILE *tmplib;
  539.  
  540.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  541.         exit(5);
  542.     }
  543.     if (!read_dir(flib,&directory)) {
  544.         exit(5);
  545.     }
  546.     if (directory.version != NEW_VERSION) {
  547.         directory.version = NEW_VERSION;
  548.         if (verbose) {
  549.             printf("Converting old to new version.\n");
  550.         }
  551.     }
  552.     if (verbose) {
  553.         printf("Old directory size: %ld, new directory size: %ld.\n",
  554.             directory.alloc, directory.total);
  555.     }
  556.     /* copy old flib */
  557.     if ((tmplib = copy_old_flib(&directory,flib,argv[2],verbose)) == NULL) {
  558.         exit(5);
  559.     }
  560.     update_dir(&directory, tmplib, verbose);
  561.     fclose(tmplib);
  562.     fclose(flib);
  563.     flib = NULL;
  564.     copy_tmpflib(directory.real_name,directory.total);
  565.   }
  566.   /**************** rename **************/
  567.   if (rename) {
  568.     struct dirlist *dirl;
  569.     int nr;
  570.  
  571.     if ((flib = open_flib(argv[2],OPEN_FOR_APPEND,&directory,(short)0)) == NULL) {
  572.         exit(5);
  573.     }
  574.     if (directory.version == OLD_VERSION) {
  575.         if (verbose) {
  576.             printf("This Option work's only with the new flib-version!\n");
  577.             printf("Convert first the flib with \"flib z %s\"\n",argv[2]);
  578.         }
  579.         else {
  580.             fprintf(stderr,"Wrong flib-version!\n");
  581.         }
  582.     }
  583.     nr = read_new_modules(term_input,argc,argv,&directory,&dirl,verbose);
  584.     if (!read_dir(flib,&directory)) {
  585.         exit(5);
  586.     }
  587.     if (!rename_entries(&directory,dirl,verbose)) {
  588.         exit(5);
  589.     }
  590.     update_dir(&directory, flib, verbose);
  591.     fclose(flib);
  592.     flib = NULL;
  593.   }
  594.   /**************** test ***************/
  595.   if (test) {
  596.     if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  597.         exit(5);
  598.     }
  599.     if (directory.version == OLD_VERSION) {
  600.         if (verbose) {
  601.             printf("This Option work's only with the new flib-version!\n");
  602.             printf("Convert first the flib with \"flib z %s\"\n",argv[2]);
  603.         }
  604.         else {
  605.             fprintf(stderr,"Wrong flib-version!\n");
  606.         }
  607.     }
  608.     else {
  609.         if (directory.alloc == 0 && !read_dir(flib,&directory)) {
  610.             exit(5);
  611.         }
  612.         test_flib(flib,&directory,verbose);
  613.     }
  614.     fclose(flib);
  615.     flib = NULL;
  616.   }
  617.   /**************** link ***************/
  618.   if (link) {
  619.     char link_name[DOSNAMESIZE];
  620.  
  621.     if ((flib = fopen(argv[2],OPEN_FOR_WRITING)) == NULL) {
  622.     }
  623.     else {
  624.         if (!fwritelong(LNKMAGIC,flib)) {
  625.             perror("*** ");
  626.             fprintf(stderr,"*** Can't write to LNK-flib \"%s\"!\n",
  627.                 argv[2]);
  628.             exit(5);
  629.         }
  630.         link_name[0] = '<';
  631.         link_name[1] = '\0';
  632.         strcat(link_name,argv[3]);
  633.         strcat(link_name,">");
  634.         if (fwrite(link_name,sizeof(char),strlen(link_name),flib) != strlen(link_name)) {
  635.             perror("*** ");
  636.             fprintf(stderr,"*** Can't write to LNK-flib \"%s\"!\n",
  637.                 argv[2]);
  638.             exit(5);
  639.         }
  640.         fclose(flib);
  641.         flib = NULL;
  642.     }
  643.   }
  644.   /**************** table **************/
  645.   if (table) {
  646.     if (flib == NULL) {
  647.         if ((flib = open_flib(argv[2],OPEN_FOR_READING,&directory,(short)0)) == NULL) {
  648.             exit(5);
  649.         }
  650.         if (directory.alloc == 0 && !read_dir(flib,&directory)) {
  651.             exit(5);
  652.         }
  653.     }
  654.     print_dir(&directory,argv[2],verbose);
  655.     fclose(flib);
  656.   }
  657. }    /* main */
  658.  
  659.  
  660. /* print the help */
  661. static void usage(pname)
  662.   char *pname;
  663. {
  664.   fprintf(stderr,HEADER,VERSION,MACHINE);
  665.   fprintf(stderr,"usage: %s c|a|x|d|z|p|l|t[v|s|e] library [-|[modules]*]\n",pname);
  666.   fprintf(stderr,"\tc,a : create library / add (replace) module(s) to (in) library,\n");
  667.   fprintf(stderr,"\tx   : extract module(s) from library,\n");
  668.   fprintf(stderr,"\td   : delete module(s) in library,\n");
  669.   fprintf(stderr,"\tt   : print table,\n");
  670.   fprintf(stderr,"\tr   : rename module(s) in library,\n");
  671.   fprintf(stderr,"\tz   : create new flib from old flib,\n");
  672.   fprintf(stderr,"\tp   : test checksums of all modules,\n");
  673.   fprintf(stderr,"\tl   : create a flib link (second arg is the link destination),\n");
  674.   fprintf(stderr,"\ts   : strip path (only with c,a),\n");
  675.   fprintf(stderr,"\te   : strip extension (only with c,a),\n");
  676.   fprintf(stderr,"\tv   : verbose mode,\n");
  677.   fprintf(stderr,"\t?   : print this help,\n");
  678.   fprintf(stderr,"\t-   : read module name(s) from stdin.\n");
  679. }
  680.  
  681.  
  682.  
  683. /* parse the first argument */
  684. static int decode_args(argc, argv, table, extract, create,
  685.         delete, compress, verbose, rename, test, link, term_input)
  686.   int argc;
  687.   char **argv;
  688.   int *table, *extract, *create, *delete, *compress, *verbose,
  689.         *rename, *test, *link, *term_input;
  690. {
  691.   char *flags;
  692.   int c;
  693.  
  694.   *table = *extract = *create = *delete = *compress = *verbose =
  695.         *rename = *test = *link = *term_input = FALSE;
  696.   strip_path = strip_ext = FALSE;
  697.  
  698.   flags = argv[1];
  699.   if (*flags == '-') {
  700.     flags++;
  701.   }
  702.   c = 0;
  703.   for (; *flags != '\0'; flags++) {
  704.     switch (*flags) {
  705.         case 'c':
  706.         case 'a': *create     = TRUE; c++; break;
  707.         case 'x': *extract    = TRUE; c++; break;
  708.         case 'd': *delete     = TRUE; c++; break;
  709.         case 'z': *compress   = TRUE; c++; break;
  710.         case 'r': *rename     = TRUE; c++; break;
  711.         case 'l': *link       = TRUE; c++; break;
  712.         case 'p': *test       = TRUE; break;
  713.         case 't': *table      = TRUE; break;
  714.         case 's': strip_path  = TRUE; break;
  715.         case 'e': strip_ext   = TRUE; break;
  716.         case 'v': *verbose    = TRUE; break;
  717.         case '?': return FALSE;
  718.         default : fprintf(stderr, "*** Unknown flag '%c'!\n",*flags);
  719.               return FALSE;
  720.     }
  721.   }
  722.   if (c >= 2) {
  723.     fprintf(stderr,"*** The flags 'c' 'x' 'd' 'z' 'r' 'l' are mutual exclusive!\n");
  724.     return FALSE;
  725.   }
  726.   if (!(*extract || *create || *delete || *table || *compress || *rename || *test || *link)) {
  727.     fprintf(stderr,"*** Missing one of the flags 'c' 'x' 'd' 'z' 't' 'p' 'l'!\n");
  728.     return FALSE;
  729.   }
  730.   if ((strip_path || strip_ext) && !*create) {
  731.     fprintf(stderr,"*** Use 's' and 'e' only with 'c' or 'a'!\n");
  732.     return FALSE;
  733.   }
  734.   if (*link && argc != 4) {
  735.     fprintf(stderr,"*** Incorrect number of arguments!\n");
  736.     return FALSE;
  737.   }
  738.   if (argc > 3 && strcmp(argv[3],"-") == 0) {
  739.     *term_input = TRUE;
  740.     if (*verbose && (*create || *extract || *delete || *rename)) {
  741.         printf("Reading module names from standard input.\n");
  742.     }
  743.   }
  744.   return TRUE;
  745. }
  746.  
  747. /* delete flib with the name "name" and rename the tmpflib to "name" */
  748. /* nr is the number of modules in the flib => nr == 0 --> no flib */
  749. static void copy_tmpflib(name, nr)
  750.   char *name;
  751.   long nr;
  752. {
  753.   if (remove(name) != 0) {
  754.     perror("*** ");
  755.     fprintf(stderr,"*** Can't remove flib \"%s\"!\n",name);
  756.   }
  757.   if (nr > 0) {
  758.     if (rename(TMPFLIB,name) != 0) {
  759.         if (!copy_file(TMPFLIB,name)) {
  760.             perror("*** ");
  761.             fprintf(stderr,"*** Can't rename temporary flib \"%s\" to \"%s\"!\n",
  762.                 TMPFLIB,name);
  763.         }
  764.         if (remove(TMPFLIB) != 0) {
  765.             perror("*** ");
  766.             fprintf(stderr,"*** Can't remove temporary flib \"%s\"!\n",TMPFLIB);
  767.         }
  768.     }
  769.   }
  770.   else {
  771.     if (remove(TMPFLIB) != 0) {
  772.         perror("*** ");
  773.         fprintf(stderr,"*** Can't remove temporary flib \"%s\"!\n",TMPFLIB);
  774.     }
  775.   }
  776. }
  777.  
  778. /* copy file source to file drain                 */
  779. static int copy_file(source, drain)
  780.   char *source;
  781.   char *drain;
  782. {
  783.   FILE *sf, *df;
  784.   long len;
  785.  
  786.   if ((sf = fopen(source,OPEN_FOR_READING)) == NULL) {
  787.     return FALSE;
  788.   }
  789.   if ((df = fopen(drain,OPEN_FOR_WRITING)) == NULL) {
  790.     fclose(sf);
  791.     return FALSE;
  792.   }
  793.   while ((len = fread(buffer,sizeof(char),BUFSIZE,sf)) == BUFSIZE) {
  794.     if (fwrite(buffer,sizeof(char),BUFSIZE,df) != BUFSIZE) {
  795.         fclose(sf);
  796.         fclose(df);
  797.         return FALSE;
  798.     }
  799.   }
  800.   if (len > 0) {
  801.     if (fwrite(buffer,sizeof(char),len,df) != len) {
  802.         fclose(sf);
  803.         fclose(df);
  804.         return FALSE;
  805.     }
  806.   }
  807.   fclose(sf);
  808.   fclose(df);
  809.   
  810.   return TRUE;
  811. }
  812.  
  813. /* create a dirlist structure entry whith the module-name "name" */
  814. static int insert_name_into_dir(name,dirl,version)
  815.   char *name;
  816.   struct dirlist **dirl;
  817.   int version;
  818. {
  819.   char newpath[NEWFILENAMELEN];
  820.   int j;
  821.   int len;
  822.   
  823.   len = module_len(name);        /* length without path-extension */
  824.   module_name(name, newpath);        /* extract path-extension */
  825.  
  826.   if ((version == NEW_VERSION && len > NEWFILENAMELEN-1) ||
  827.         (version == OLD_VERSION && len > FILENAMELEN-1)) {
  828.     fprintf(stderr,"*** Module name \"%s\" too long!\n",name);
  829.     return FALSE;
  830.   }
  831.   if ((*dirl = (struct dirlist *)
  832.         malloc(sizeof(struct dirlist))) == NULL) {
  833.     fprintf(stderr,"*** No memory for internal flib directory!\n");
  834.     exit(5);
  835.   }
  836.   for (j=0; j<NEWFILENAMELEN; j++) {    /* clear the string */
  837.     (*dirl)->dirent.mname[j] = '\0';
  838.   }
  839.   strncpy((*dirl)->dirent.mname,newpath,NEWFILENAMELEN);
  840.   (*dirl)->dirent.size  = 0L;
  841.   (*dirl)->dirent.where = 0L;
  842.   (*dirl)->next = NULL;
  843.   if (((*dirl)->dirent.real_path = strdup(name)) == NULL) {
  844.     fprintf(stderr,"*** No memory for internal flib directory!\n");
  845.     exit(5);
  846.   }
  847.   return TRUE;
  848. }
  849.  
  850.  
  851. /* calculates the length of a module name */
  852. static int module_len(name)
  853.     char * name;
  854. {
  855.   int len;
  856.   char * ptr;
  857.  
  858.   len = strlen(name);
  859.  
  860.   if (strip_path) {
  861.     ptr = strrchr(name, '/');
  862. #ifdef AMIGA
  863.     if (!ptr) ptr = strchr(name, ':');
  864. #endif
  865.     if (ptr) len -= (ptr-name+1);
  866.   }
  867.   if (strip_ext) {
  868.     ptr = strrchr(name, '.');
  869.     if (ptr) len -= strlen(ptr);
  870.   }
  871.  
  872.   return len;
  873. }
  874.  
  875. /* is module from "test" in "inp1" or "inp2" ? */
  876. static struct dirlist *exist_entry(inp1, inp2, test)
  877.   struct dirlist *inp1, *inp2;
  878.   struct dirlist *test;        /* only one entry in list */
  879. {
  880.   char *name = test->dirent.mname;
  881.  
  882.   for (; inp1 != NULL && strcmp(name,inp1->dirent.mname) != 0; inp1 = inp1->next);
  883.   if (inp1 != NULL) {
  884.     return inp1;
  885.   }
  886.   for (; inp2 != NULL && strcmp(name,inp2->dirent.mname) != 0; inp2 = inp2->next);
  887.   if (inp2 != NULL) {
  888.     return inp2;
  889.   }
  890.   return NULL;
  891. }
  892.  
  893. /* read a list of modules from argv or from stdin */
  894. static int read_new_modules(term_input,argc,argv,directory,start_dirl,verbose)
  895.   int term_input;
  896.   int argc;
  897.   char **argv;
  898.   struct dir *directory;
  899.   struct dirlist **start_dirl;
  900.   int verbose;
  901. {
  902.   int nr_modules, i;
  903.   struct dirlist *dirl, *old_dirl, *find_old;
  904.   char input[256];
  905.  
  906.   old_dirl = dirl = NULL;
  907.   nr_modules = 0;
  908.   *start_dirl = NULL;
  909.  
  910.   if (term_input) {
  911.     while (!feof(stdin)) {
  912.         if (gets(input) != NULL) {
  913.             if (insert_name_into_dir(input, &dirl,directory->version)) {
  914.                 if ((find_old = exist_entry(directory->dirlist,
  915.                         *start_dirl,dirl)) != NULL) {
  916.                     /* the module is already in the lib */
  917.                     /* replace it */
  918.                     find_old->dirent.where = 0L;
  919.                     /* now it must new inserted */
  920.                     if (verbose) {
  921.                         printf("Replacing module \"%s\".\n",
  922.                             find_old->dirent.mname);
  923.                     }
  924.                 }
  925.                 else {
  926.                     nr_modules++;
  927.                     if (old_dirl == NULL) {
  928.                         *start_dirl = dirl;
  929.                     }
  930.                     else {
  931.                         old_dirl->next = dirl;
  932.                     }
  933.                     old_dirl = dirl;
  934.                 }
  935.             }
  936.         }
  937.     }
  938.   }
  939.   else {
  940.     for (i=3; i<argc; i++) {
  941.         if (insert_name_into_dir(argv[i], &dirl, directory->version)) {
  942.             if ((find_old = exist_entry(directory->dirlist,
  943.                         *start_dirl,dirl)) != NULL) {
  944.                 /* the module is already in the lib */
  945.                 /* replace it */
  946.                 find_old->dirent.where = 0L;
  947.                 /* now it must new inserted */
  948.                 if (verbose) {
  949.                     printf("Replacing module \"%s\".\n",
  950.                         find_old->dirent.mname);
  951.                 }
  952.             }
  953.             else {
  954.                 nr_modules++;
  955.                 if (old_dirl == NULL) {
  956.                     *start_dirl = dirl;
  957.                 }
  958.                 else {
  959.                     old_dirl->next = dirl;
  960.                 }
  961.                 old_dirl = dirl;
  962.             }
  963.         }
  964.     }
  965.   }
  966.   if (dirl != NULL) {
  967.     dirl->next = NULL;
  968.   }
  969.   return nr_modules;
  970. }
  971.  
  972.  
  973. /* open a flib and test the magic-number */
  974. static FILE *open_flib(name,mode,directory,levels)
  975.   char *name;
  976.   char *mode;
  977.   struct dir *directory;
  978.   short levels;
  979. {
  980.   static char link_name[DOSNAMESIZE];
  981.   char newname[DOSNAMESIZE], *ptr, *p;
  982.   FILE *f;
  983.   long magic;
  984.  
  985.   directory->is_link = FALSE;
  986.   directory->real_name[0] = '\0';
  987.  
  988.   if ((f = fopen(name,mode)) == NULL) {
  989.     fprintf(stderr,"*** Can't open library \"%s\"!\n",name);
  990.     return NULL;
  991.   }
  992.   if (!freadlong(&magic,f) ||
  993.     (magic != LIBMAGIC && magic != OLD_LIBMAGIC && magic != LNKMAGIC)) {
  994.         fclose(f);
  995.         fprintf(stderr,"*** File \"%s\" isn't a font library!\n",name);
  996.         return NULL;
  997.   }
  998.   if (magic == LNKMAGIC) {    
  999.     (void)fread(link_name,sizeof(char),DOSNAMESIZE,f);
  1000.     fclose(f);
  1001.     if (link_name[0] != '<') {
  1002.         fprintf(stderr,"*** Illegal flib-link \"%s\"!\n",name);
  1003.         return NULL;
  1004.     }
  1005.     ptr = strrchr(link_name,'>');
  1006.     if (ptr == NULL) {
  1007.         fprintf(stderr,"*** Illegal flib-link \"%s\"!\n",name);
  1008.         return NULL;
  1009.     }
  1010.     levels++;
  1011.     if (levels > MAXLINKLEVELS) {
  1012.         fprintf(stderr,"*** To many link levels!\n");
  1013.         return NULL;
  1014.     }
  1015.     *ptr = '\0';
  1016.     ptr = link_name;
  1017.     ptr++;
  1018.     strcpy(newname, name);
  1019.     /* is 'ptr' (target of the link) a relative path ? */
  1020.     if (
  1021. #ifdef AMIGA
  1022.         strchr(ptr,':') == NULL
  1023. #else
  1024. # ifdef ATARI
  1025.         !((*ptr & 0x40) == 0x40 && *(ptr + 1) == ':')
  1026. # else
  1027.         *ptr != '/'
  1028. # endif
  1029. #endif
  1030.         ) {
  1031.         /* if yes, take the dir of the link-file and append the target name */
  1032.         if ((p = strrchr(newname,'/')) == NULL) {
  1033.           p = strchr(newname,':');
  1034.           /* if the link-file has no dir -> ok, we are already in the right dir */
  1035.         }
  1036.         if (p != NULL) {
  1037.           *(p+1) = '\0';
  1038.           strcat(newname, ptr);
  1039.           ptr = strcpy(link_name, newname);
  1040.         }
  1041.     }
  1042.     f = open_flib(ptr,mode,directory,levels);
  1043.     directory->is_link = TRUE;
  1044.   }
  1045.   else {
  1046.     if (magic == LIBMAGIC) {
  1047.         directory->version = NEW_VERSION;
  1048.     }
  1049.     else {
  1050.         directory->version = OLD_VERSION;
  1051.     }
  1052.     strcpy(directory->real_name,name);
  1053.   }
  1054.  
  1055.   return f;
  1056. }
  1057.  
  1058. /* read the directory from the flib (file-pointer must be on the first dir) */
  1059. /* only this directory entries a correct where "where != 0" the others are unused */
  1060. static int read_dir(f,directory)
  1061.   FILE *f;
  1062.   struct dir *directory;
  1063. {
  1064.   long alloc;
  1065.   union direntry dir;
  1066.   struct dirlist *direntr, *old_direntry;
  1067.   int i, j, nr;
  1068.  
  1069.   if (!freadlong(&alloc,f)) {
  1070.     fprintf(stderr,"*** Error while reading internal flib directory!\n");
  1071.     return FALSE;
  1072.   }
  1073.   direntr = old_direntry = NULL;
  1074.   for (i=0, nr=0; i<alloc && !feof(f); i++) {
  1075.     if (!freaddir(&dir,directory->version,f)) {
  1076.         fprintf(stderr,"*** Error while reading internal flib directory!\n");
  1077.         return FALSE;
  1078.     }
  1079.     if ((directory->version == NEW_VERSION && dir.new.where != 0) ||    /* used entry */
  1080.         (directory->version == OLD_VERSION && dir.old.where != 0)) {
  1081.         nr++;
  1082.         if ((direntr = (struct dirlist *)
  1083.                 malloc(sizeof(struct dirlist))) == NULL) {
  1084.             fprintf(stderr,"*** No memory for internal flib directory!\n");
  1085.             return FALSE;
  1086.         }
  1087.         direntr->dirent.real_path = NULL;
  1088.         for (j=0; j<NEWFILENAMELEN; j++) {    /* clear the string */
  1089.             direntr->dirent.mname[j] = '\0';
  1090.         }
  1091.         if (old_direntry == NULL ) {
  1092.             directory->dirlist = direntr;
  1093.         }
  1094.         else {
  1095.             old_direntry->next = direntr;
  1096.         }
  1097.         if (directory->version == NEW_VERSION) {
  1098.             direntr->dirent = dir.new;
  1099.         }
  1100.         else {
  1101.             strncpy(direntr->dirent.mname,dir.old.mname,FILENAMELEN);
  1102.             direntr->dirent.size     = dir.old.size;
  1103.             direntr->dirent.where    = dir.old.where;
  1104.             direntr->dirent.checksum = 0;
  1105.         }
  1106.         old_direntry = direntr;
  1107.     }
  1108.   }
  1109.   if (direntr != NULL) {
  1110.     direntr->next = NULL;
  1111.   }
  1112.   directory->total    = nr;
  1113.   directory->alloc    = alloc;
  1114.   if (nr == 0) {
  1115.     directory->dirlist = NULL;
  1116.   }
  1117.   return TRUE;
  1118. }
  1119.  
  1120. /* print the contents of the directory */
  1121. static void print_dir(directory, lib_name, verbose)
  1122.   struct dir *directory;
  1123.   char *lib_name;
  1124.   int verbose;
  1125.   struct dirlist *temp;
  1126.  
  1127.   if (verbose) {
  1128.     if (directory->total == 1) {
  1129.         printf ("Library contains one module. ");
  1130.     }
  1131.     else {
  1132.         printf ("Library contains %ld modules. ",directory->total);
  1133.     }
  1134.     if (directory->alloc == 1) {
  1135.         printf ("Directory size is one module.\n");
  1136.     }
  1137.     else {
  1138.         printf ("Directory size is %ld modules.\n",directory->alloc);
  1139.     }
  1140.     if (directory->is_link) {
  1141.         printf ("The library \"%s\" is a link to \"%s\"!\n",
  1142.                 lib_name, directory->real_name);
  1143.     }
  1144.     if (directory->version == OLD_VERSION) {
  1145.         printf ("WARNING: That's an old library-version!\n");
  1146.     }
  1147.     printf ("\n  Module name           Size   Position\n");
  1148.     printf ("  --------------------- ------ --------\n");
  1149.     for (temp = directory->dirlist; temp != NULL; temp = temp->next) {
  1150.         printf ("  %-21s %6ld %8ld\n", temp->dirent.mname,
  1151.             temp->dirent.size, temp->dirent.where);
  1152.     }
  1153.     printf("\n");
  1154.   }
  1155.   else {
  1156.     for (temp = directory->dirlist; temp != NULL; temp = temp->next) {
  1157.         puts(temp->dirent.mname);
  1158.     }
  1159.   }
  1160.   
  1161. }
  1162.  
  1163. /* search a module in the flib and copy it to a new file */
  1164. static int ex_module(directory, mname, flib, verbose)
  1165.   struct dir *directory;
  1166.   char *mname;
  1167.   FILE *flib;
  1168.   int verbose;
  1169. {
  1170.   struct dirlist *temp;
  1171.   FILE *module;
  1172.   int i, j, count;
  1173.   unsigned short check;
  1174.  
  1175.   if (directory == NULL || flib == NULL) {
  1176.     fprintf(stderr,"*** Internal error!\n");
  1177.     return FALSE;
  1178.   }
  1179.  
  1180.   /* find the module */
  1181.   for (temp = directory->dirlist; temp != NULL
  1182.     && strcmp(temp->dirent.mname,mname) != 0; temp = temp->next);
  1183.  
  1184.   if (temp == NULL) {
  1185.     fprintf(stderr,"*** Can't find module \"%s\"!\n",mname);
  1186.     return FALSE;
  1187.   }
  1188.  
  1189.   if (verbose) {
  1190.     printf("Extracting module %s \t(%ld bytes).\n",mname, temp->dirent.size);
  1191.   }
  1192.  
  1193.   if (fseek(flib,temp->dirent.where,0) != 0) {
  1194.     perror("*** ");
  1195.     fprintf(stderr,"*** Error during fseek!\n");
  1196.     return FALSE;
  1197.   }
  1198.   if ((module = fopen(mname,OPEN_FOR_WRITING)) == NULL) {
  1199.     fprintf(stderr,"*** Can't create file \"%s\"!\n",mname);
  1200.     return FALSE;
  1201.   }
  1202.  
  1203.   count = temp->dirent.size / BUFSIZE;
  1204.   check = 0;
  1205.   for (i=0; i<count; i++) {
  1206.     if (fread(buffer,sizeof(char),BUFSIZE,flib)!=BUFSIZE) {
  1207.         fclose(module);
  1208.         fprintf(stderr,"*** Can't read from flib!\n");
  1209.         return FALSE;
  1210.     }
  1211.     for (j=0; j<BUFSIZE; j++) {
  1212.         check += (unsigned short)buffer[j];
  1213.     }
  1214.     if (fwrite(buffer,sizeof(char),BUFSIZE,module) != BUFSIZE) {
  1215.         fclose(module);
  1216.         fprintf(stderr,"*** Can't write to module %s!\n",mname);
  1217.         return FALSE;
  1218.     }
  1219.   }
  1220.   i = temp->dirent.size - count * BUFSIZE;    /* copy rest */
  1221.   if (i > 0) {
  1222.     if (fread(buffer,sizeof(char),i,flib) != i) {
  1223.         fclose(module);
  1224.         fprintf(stderr,"*** Can't read from flib!\n");
  1225.         return FALSE;
  1226.     }
  1227.     for (j=0; j<i; j++) {
  1228.         check += buffer[j];
  1229.     }
  1230.     if (fwrite(buffer,sizeof(char),i,module) != i) {
  1231.         fclose(module);
  1232.         fprintf(stderr,"*** Can't write to module %s!\n",mname);
  1233.         return FALSE;
  1234.     }
  1235.   }
  1236.  
  1237.   fclose(module);
  1238.   if (directory->version != OLD_VERSION && check != temp->dirent.checksum) {
  1239.     fprintf(stderr,"*** WARNING: Module \"%s\" extracted with wrong checksum!\n",
  1240.                 mname);
  1241.   }
  1242.  
  1243.   return TRUE;
  1244. }
  1245.  
  1246. /* create a complete (new) flib, copy only files into the flib */
  1247. static int create_new_flib(directory, name, verbose)
  1248.   struct dir *directory;
  1249.   char *name;
  1250.   int verbose;
  1251. {
  1252.   FILE *flib;
  1253.   struct dirlist *dirl;
  1254.   long size=0, where=0;
  1255.   unsigned short check;
  1256.  
  1257.   if ((flib = copy_directory(directory, name, verbose)) == NULL) {
  1258.     return FALSE;
  1259.   }
  1260.  
  1261.   /* module abspeichern */
  1262.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1263.     if (verbose) {
  1264.         printf("Copying module \"%s\"\t... ",dirl->dirent.mname);
  1265.     }
  1266.     if (!copy_module(dirl->dirent.mname,dirl->dirent.real_path,flib,&size,&where,&check)) {
  1267.         fprintf(stderr,"\n*** Can't copy module \"%s\" to library!\n",
  1268.                 dirl->dirent.mname);
  1269.         return FALSE;
  1270.     }
  1271.     if (verbose) {
  1272.         printf("ok. \t(%ld bytes at %ld)\n",size,where);
  1273.     }
  1274.     dirl->dirent.size     = size;
  1275.     dirl->dirent.where    = where;
  1276.     dirl->dirent.checksum = check;
  1277.   }
  1278.   update_dir(directory, flib, verbose);
  1279.  
  1280.   return TRUE;
  1281. }
  1282.  
  1283.  
  1284. /* create a new flib and prepare the directory part */
  1285. static FILE *copy_directory(directory, name, verbose)
  1286.   struct dir *directory;
  1287.   char *name;
  1288.   int verbose;
  1289. {
  1290.   FILE *flib;
  1291.   long magic = (directory->version == NEW_VERSION) ? LIBMAGIC : OLD_LIBMAGIC;
  1292.   struct dirlist *dirl;
  1293.   union direntry dir;
  1294.  
  1295.   if ((flib = fopen(name,OPEN_FOR_WRITING)) == NULL) {
  1296.     fprintf(stderr,"*** Can't open destination library!\n");
  1297.     return NULL;
  1298.   }
  1299.   if (!fwritelong(magic,flib) || !fwritelong(directory->total,flib)) {
  1300.     fprintf(stderr,"*** Can't write to destination library!\n");
  1301.     return NULL;
  1302.   }
  1303.   /* directory anlegen */
  1304.   if (verbose) {
  1305.     printf("Creating internal flib directory\t... ");
  1306.   }
  1307.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1308.     if (directory->version == NEW_VERSION) {
  1309.         dir.new = dirl->dirent;
  1310.     }
  1311.     else {
  1312.         strncpy(dir.old.mname,dirl->dirent.mname,FILENAMELEN);
  1313.         dir.old.size  = dirl->dirent.size;
  1314.         dir.old.where = dirl->dirent.where;
  1315.     }
  1316.     if (!fwritedir(&dir,directory->version,flib)) {
  1317.         fprintf(stderr,"*** Can't write to destination library!\n");
  1318.         return NULL;
  1319.     }
  1320.   }
  1321.   if (verbose) {
  1322.     printf("ok.\n");
  1323.   }
  1324.   return flib;
  1325. }
  1326.  
  1327. /* copy a module (file) to the actual position in flib */
  1328. static int copy_module(name, real_path, flib, size, where, check)
  1329.   char *name;
  1330.   char *real_path;
  1331.   FILE *flib;
  1332.   long *size, *where;
  1333.   unsigned short *check;
  1334. {
  1335.   FILE *module;
  1336.   int len, i;
  1337.   char *open_name;
  1338.   
  1339.   if (real_path != NULL) {
  1340.     open_name = real_path;
  1341.   }
  1342.   else {
  1343.     open_name = name;
  1344.   }
  1345.  
  1346.   if ((module = fopen(open_name,OPEN_FOR_READING)) == NULL) {
  1347.     return FALSE;
  1348.   }
  1349.   *size = 0;
  1350.   *where = ftell(flib);
  1351.   *check = 0;
  1352.   while ((len = fread(buffer,sizeof(char),BUFSIZE,module)) == BUFSIZE) {
  1353.     if (fwrite(buffer,sizeof(char),BUFSIZE,flib) != BUFSIZE) {
  1354.         fclose(module);
  1355.         return FALSE;
  1356.     }
  1357.     *size += BUFSIZE;
  1358.     for (i=0; i<BUFSIZE; i++) {
  1359.         *check += (unsigned short)buffer[i];
  1360.     }
  1361.   }
  1362.   if (len > 0) {
  1363.     if (fwrite(buffer,sizeof(char),len,flib) != len) {
  1364.         fclose(module);
  1365.         return FALSE;
  1366.     }
  1367.     *size += len;
  1368.     for (i=0; i<len; i++) {
  1369.         *check += (unsigned short)buffer[i];
  1370.     }
  1371.   }
  1372.   fclose(module);
  1373.  
  1374.   return TRUE;
  1375. }
  1376.  
  1377. /* copy the modules (from flib) with "where != 0" to flib (tmplib) */
  1378. static FILE *copy_old_flib(directory, flib, name, verbose)
  1379.   struct dir *directory;
  1380.   FILE *flib;
  1381.   char *name;
  1382.   int verbose;
  1383. {
  1384.   FILE *tmplib;
  1385.   struct dirlist *dirl;
  1386.   long where;
  1387.   int i, j;
  1388.   long len ,count;
  1389.   unsigned short check;
  1390.  
  1391.   if ((tmplib = copy_directory(directory, TMPFLIB, verbose)) == NULL) {
  1392.     return NULL;
  1393.   }
  1394.  
  1395.   /* module copy */
  1396.   for (dirl = directory->dirlist; dirl != NULL;    dirl = dirl->next) {
  1397.     if (dirl->dirent.where != 0L) {
  1398.         if (verbose) {
  1399.             printf("Copying module \"%s\"\t... ",dirl->dirent.mname);
  1400.         }
  1401.         if (fseek(flib,dirl->dirent.where,0) != 0) {
  1402.             perror("*** ");
  1403.             fprintf(stderr,"*** Error during fseek!\n");
  1404.             return NULL;
  1405.         }
  1406.         where = ftell(tmplib);
  1407.         count = dirl->dirent.size / BUFSIZE;
  1408.         check = 0;
  1409.         for (i=0; i<count; i++) {
  1410.             if (fread(buffer,sizeof(char),BUFSIZE,flib)!=BUFSIZE) {
  1411.                 fclose(tmplib);
  1412.                 fprintf(stderr,"*** Can't read from flib!\n");
  1413.                 return NULL;
  1414.             }
  1415.             for (j=0; j<BUFSIZE; j++) {
  1416.                 check += (unsigned short)buffer[j];
  1417.             }
  1418.             if (fwrite(buffer,sizeof(char),BUFSIZE,tmplib) != BUFSIZE) {
  1419.                 fclose(tmplib);
  1420.                 fprintf(stderr,"*** Can't write to temporary flib!\n");
  1421.                 return NULL;
  1422.             }
  1423.         }
  1424.         len = dirl->dirent.size - count * BUFSIZE;
  1425.         if (len > 0) {
  1426.             if (fread(buffer,sizeof(char),(int)len,flib) != len) {
  1427.                 fclose(tmplib);
  1428.                 fprintf(stderr,"*** Can't read from flib!\n");
  1429.                 return NULL;
  1430.             }
  1431.             for (j=0; j<len; j++) {
  1432.                 check += (unsigned short)buffer[j];
  1433.             }
  1434.             if (fwrite(buffer,sizeof(char),(int)len,tmplib) != len) {
  1435.                 fclose(tmplib);
  1436.                 fprintf(stderr,"*** Can't write to temporary flib!\n");
  1437.                 return NULL;
  1438.             }
  1439.         }
  1440.         dirl->dirent.where = where;
  1441.         dirl->dirent.checksum = check;
  1442.         if (verbose) {
  1443.             printf("ok.\n");
  1444.         }
  1445.     }
  1446.   }
  1447.   return tmplib;
  1448. }
  1449.  
  1450. /* copy the modules (files) with "where == 0" to flib (tmplib) */
  1451. static int append_modules_to_flib(directory, flib, verbose)
  1452.   struct dir *directory;
  1453.   FILE *flib;
  1454.   int verbose;
  1455. {
  1456.   struct dirlist *dirl;
  1457.   long size, where;
  1458.   unsigned short check;
  1459.  
  1460.   /* module abspeichern */
  1461.   if (fseek(flib,0L,2) != 0) {        /* end of file */
  1462.     perror("*** ");
  1463.     fprintf(stderr,"*** Error during fseek!\n");
  1464.     return 0;
  1465.   }
  1466.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1467.     if (dirl->dirent.where == 0L) {
  1468.         if (verbose) {
  1469.             printf("Copying module \"%s\"\t... ",dirl->dirent.mname);
  1470.         }
  1471.         if (!copy_module(dirl->dirent.mname,dirl->dirent.real_path,flib,&size,&where,&check)) {
  1472.             fprintf(stderr,"\n*** Can't copy module \"%s\" to library!\n");
  1473.             return FALSE;
  1474.         }
  1475.         if (verbose) {
  1476.             printf("ok. \t(%ld bytes at %ld)\n",size,where);
  1477.         }
  1478.         dirl->dirent.size     = size;
  1479.         dirl->dirent.where    = where;
  1480.         dirl->dirent.checksum = check;
  1481.     }
  1482.   }
  1483.   return update_dir(directory, flib, verbose);
  1484. }
  1485.  
  1486. /* find a module and delete it from the directory list */
  1487. static int del_module_from_dir(directory, name, verbose)
  1488.   struct dir *directory;
  1489.   char *name;
  1490.   int verbose;
  1491. {
  1492.   struct dirlist *temp, *parent;
  1493.  
  1494.   if (directory == NULL) {
  1495.     fprintf(stderr,"*** Internal error!\n");
  1496.     return FALSE;
  1497.   }
  1498.  
  1499.   /* find the module */
  1500.   for (temp = directory->dirlist, parent = NULL; temp != NULL
  1501.     && strcmp(temp->dirent.mname,name) != 0;
  1502.     parent = temp, temp = temp->next);
  1503.  
  1504.   if (temp == NULL) {
  1505.     fprintf(stderr,"*** Can't find module \"%s\"!\n",name);
  1506.     return FALSE;
  1507.   }
  1508.   /* delete module from directory-list */
  1509.   if (parent == NULL) {
  1510.     directory->dirlist = temp->next;
  1511.   }
  1512.   else {
  1513.     parent->next = temp->next;
  1514.   }
  1515.   free(temp);
  1516.   directory->alloc = --directory->total;
  1517.  
  1518.   return TRUE;
  1519. }
  1520.  
  1521. /* save directory to file */
  1522. static int update_dir(directory, flib, verbose)
  1523.   struct dir *directory;
  1524.   FILE *flib;
  1525.   int verbose;
  1526. {
  1527.   struct dirlist *dirl;
  1528.   union direntry dir;
  1529.  
  1530.   /* directory size-where */
  1531.   if (verbose) {
  1532.     printf("Updating internal flib directory\t... ");
  1533.   }
  1534.   if (fseek(flib,8L,0) != 0) {
  1535.     perror("*** ");
  1536.     fprintf(stderr,"*** Can't fseek?!\n");
  1537.     return FALSE;
  1538.   }
  1539.   for (dirl = directory->dirlist; dirl != NULL; dirl = dirl->next) {
  1540.     if (directory->version == NEW_VERSION) {
  1541.         dir.new = dirl->dirent;
  1542.         upd_font_name(&dir.new);
  1543.     }
  1544.     else {
  1545.         strncpy(dir.old.mname,dirl->dirent.mname,FILENAMELEN);
  1546.         dir.old.size  = dirl->dirent.size;
  1547.         dir.old.where = dirl->dirent.where;
  1548.     }
  1549.     if (!fwritedir(&dir,directory->version,flib)) {
  1550.         fprintf(stderr,"*** Can't write to destination library!\n");
  1551.         return FALSE;
  1552.     }
  1553.   }
  1554.   if (verbose) {
  1555.     printf("ok.\n");
  1556.   }
  1557.   return TRUE;
  1558. }
  1559.  
  1560.  
  1561. /* extract module name from old and copies it to new */
  1562. /* new must point to a char array of at least MEWFILENAMELEN chars */
  1563. static void module_name(old, new)
  1564.     char *old, *new;
  1565. {
  1566.   char * ptr;
  1567.  
  1568.   if (strip_path) {
  1569.     ptr = strrchr(old, '/');
  1570. #ifdef AMIGA
  1571.     if (!ptr) ptr = strchr(old, ':');
  1572. #endif
  1573.     if (ptr) {
  1574.         /* delete path */
  1575.         ptr++;
  1576.         strncpy(new, ptr, NEWFILENAMELEN);
  1577.     }
  1578.     else {
  1579.         strncpy(new, old, NEWFILENAMELEN);
  1580.     }
  1581.   }
  1582.   else {
  1583.     strncpy(new, old, NEWFILENAMELEN);
  1584.   }
  1585.  
  1586.   if (strip_ext) {
  1587.     ptr = strrchr(new, '.');
  1588.     if (ptr) {
  1589.         /* delete extension */
  1590.         char * ptr2;
  1591.         for (ptr2 = ptr; ptr2 < new+NEWFILENAMELEN; ptr2++) {
  1592.             *ptr2 = '\0';
  1593.         }
  1594.     }
  1595.   }
  1596. }
  1597.  
  1598.  
  1599. /* Change ndir.mname[] according to the flags strip_path and strip_ext */
  1600. static void upd_font_name(ndir)
  1601.     struct new_flib_dirent * ndir;
  1602. {
  1603.   char newpath[NEWFILENAMELEN];
  1604.  
  1605.   module_name(ndir->mname, newpath);
  1606.   
  1607.   strncpy(ndir->mname, newpath, NEWFILENAMELEN);
  1608. }
  1609.  
  1610.  
  1611. /* change module-names in directory                */
  1612. /* if dirl empty then change all names in directory        */
  1613. static int rename_entries(directory,dirl,verbose)
  1614.   struct dir     *directory;
  1615.   struct dirlist *dirl;
  1616.   int         verbose;
  1617. {
  1618.   struct dirlist *entry, *found;
  1619.   char str[256];
  1620.   int allowed_length = (directory->version == NEW_VERSION)
  1621.                 ? NEWFILENAMELEN
  1622.                 : FILENAMELEN;
  1623.  
  1624.  
  1625.   if (dirl == NULL) {        /* no modules -> change all names */
  1626.     for (entry = directory->dirlist; entry != NULL; entry = entry->next) {
  1627.         do {
  1628.             printf("Old name: %s, change it to: ",entry->dirent.mname);
  1629.             if (gets(str) == NULL) {
  1630.                 fprintf(stderr,"\nUnexpected end of \"stdin\"!?\n");
  1631.                 return FALSE;
  1632.             }
  1633.             if (strlen(str) > allowed_length) {
  1634.                 fprintf(stderr,"New name too long!\n");
  1635.             }
  1636.         } while (strlen(str) > allowed_length);
  1637.         if (str[0] != '\0') {
  1638.             if (verbose) {
  1639.                 printf("%s ---> %s\n",entry->dirent.mname,str);
  1640.             }
  1641.             strcpy(entry->dirent.mname,str);
  1642.         }
  1643.     }
  1644.   }
  1645.   else {            /* change only the names of the given modules */
  1646.     for (entry = dirl; entry != NULL; entry = entry->next) {
  1647.         if ((found = exist_entry(NULL,directory->dirlist,entry)) != NULL) {
  1648.             do {
  1649.                 printf("Old name: %s, change it to: ",
  1650.                         found->dirent.mname);
  1651.                 if (gets(str) == NULL) {
  1652.                     fprintf(stderr,"\nUnexpected end of \"stdin\"!?\n");
  1653.                     return FALSE;
  1654.                 }
  1655.                 if (strlen(str) > allowed_length) {
  1656.                     fprintf(stderr,"New name too long!\n");
  1657.                 }
  1658.             } while (strlen(str) > allowed_length);
  1659.             if (str[0] != '\0') {
  1660.                 if (verbose) {
  1661.                     printf("%s ---> %s\n",found->dirent.mname,str);
  1662.                 }
  1663.                 strcpy(found->dirent.mname,str);
  1664.             }
  1665.         }
  1666.     }
  1667.   }
  1668.   return TRUE;
  1669. }
  1670.  
  1671.  
  1672. /* test all checksums of the fontlibrary            */
  1673. static void test_flib(flib, directory, verbose)
  1674.   FILE *flib;
  1675.   struct dir *directory;
  1676.   int verbose;
  1677. {
  1678.   int i, j;
  1679.   struct dirlist *dirl;
  1680.   unsigned short check;
  1681.   long count, len;
  1682.  
  1683.   for (dirl = directory->dirlist; dirl != NULL;    dirl = dirl->next) {
  1684.     if (dirl->dirent.where != 0L) {
  1685.         if (verbose) {
  1686.             printf("Checking module \"%s\"\t... ",dirl->dirent.mname);
  1687.         }
  1688.         if (fseek(flib,dirl->dirent.where,0) != 0) {
  1689.             perror("*** ");
  1690.             fprintf(stderr,"*** Error during fseek!\n");
  1691.             return;
  1692.         }
  1693.         count = dirl->dirent.size / (long)BUFSIZE;
  1694.         check = 0;
  1695.         for (i=0; i<count; i++) {
  1696.             if (fread(buffer,sizeof(char),BUFSIZE,flib)!=BUFSIZE) {
  1697.                 fprintf(stderr,"*** Can't read from flib!\n");
  1698.                 return;
  1699.             }
  1700.             for (j=0; j<BUFSIZE; j++) {
  1701.                 check += (unsigned short)buffer[j];
  1702.             }
  1703.         }
  1704.         len = dirl->dirent.size - count * (long)BUFSIZE;
  1705.         if (len > 0) {
  1706.             if (fread(buffer,sizeof(char),(int)len,flib) != len) {
  1707.                 fprintf(stderr,"*** Can't read from flib!\n");
  1708.                 return;
  1709.             }
  1710.             for (j=0; j<len; j++) {
  1711.                 check += (unsigned short)buffer[j];
  1712.             }
  1713.         }
  1714.         if (dirl->dirent.checksum == check) {
  1715.             if (verbose) {
  1716.                 printf("ok.\n");
  1717.             }
  1718.         }
  1719.         else {
  1720.             if (verbose) {
  1721.                 printf("ERROR (expected %u, found %u)\n",
  1722.                     dirl->dirent.checksum, check);
  1723.             }
  1724.             else {
  1725.                 fprintf(stderr,
  1726.                       "ERROR: module \"%s\" (expected %u, found %u)\n",
  1727.                   dirl->dirent.mname, dirl->dirent.checksum, check);
  1728.             }
  1729.         }
  1730.     }
  1731.   }
  1732. }
  1733.  
  1734.  
  1735. /* read the directory structure                    */
  1736. static int freaddir(dir,version,f)
  1737.   union direntry *dir;
  1738.   int version;
  1739.   FILE *f;
  1740. {
  1741.   if (version == OLD_VERSION) {
  1742.     if (fread(dir->old.mname,FILENAMELEN,1,f) != 1) {
  1743.         return FALSE;
  1744.     }
  1745.     dir->new.mname[FILENAMELEN] = '\0';
  1746.     if (!freadlong(&(dir->old.size),f)) {
  1747.         return FALSE;
  1748.     }
  1749.     if (!freadlong(&(dir->old.where),f)) {
  1750.         return FALSE;
  1751.     }
  1752.   }
  1753.   else {
  1754.     if (fread(dir->new.mname,1,NEWFILENAMELEN,f) != NEWFILENAMELEN) {
  1755.         return FALSE;
  1756.     }
  1757.     if (!freadshort(&(dir->new.checksum),f)) {
  1758.         return FALSE;
  1759.     }
  1760.     if (!freadlong(&(dir->new.size),f)) {
  1761.         return FALSE;
  1762.     }
  1763.     if (!freadlong(&(dir->new.where),f)) {
  1764.         return FALSE;
  1765.     }    
  1766.   }
  1767.   return TRUE;
  1768. }
  1769.  
  1770.  
  1771. /* read a four byte number <hihi lohi hilo lolo> */
  1772. static int freadlong(buf,f)
  1773.   long *buf;
  1774.   FILE *f;
  1775. {
  1776.   unsigned char b[4];
  1777.  
  1778.   if (fread((char *)b,1,4,f) != 4) {
  1779.     return FALSE;
  1780.   }
  1781.   *buf = (long)(((unsigned long)b[0]) << 24) | (((unsigned long)b[1]) << 16) | 
  1782.             (((unsigned long)b[2]) << 8) | ((unsigned long)b[3]);
  1783.  
  1784.   return TRUE;
  1785. }
  1786.  
  1787. /* read a two byte number <hi lo> */
  1788. static int freadshort(buf,f)
  1789.   unsigned short *buf;
  1790.   FILE *f;
  1791. {
  1792.   unsigned char b[2];
  1793.  
  1794.   if (fread((char *)b,1,2,f) != 2) {
  1795.     return FALSE;
  1796.   }
  1797.   *buf = (unsigned short) (((unsigned short)b[0]) << 8) | ((unsigned short)b[1]);
  1798.  
  1799.   return TRUE;
  1800. }
  1801.  
  1802.  
  1803. /* write the directory structure                */
  1804. static int fwritedir(dir,version,f)
  1805.   union direntry *dir;
  1806.   int version;
  1807.   FILE *f;
  1808. {
  1809.   if (version == OLD_VERSION) {
  1810.     if (fwrite(dir->new.mname,NEWFILENAMELEN,1,f) != 1) {
  1811.         return FALSE;
  1812.     }
  1813.     if (!fwritelong(dir->new.size,f)) {
  1814.         return FALSE;
  1815.     }
  1816.     if (!fwritelong(dir->new.where,f)) {
  1817.         return FALSE;
  1818.     }
  1819.   }
  1820.   else {
  1821.     if (fwrite(dir->new.mname,NEWFILENAMELEN,1,f) != 1) {
  1822.         return FALSE;
  1823.     }
  1824.     if (!fwriteshort(dir->new.checksum,f)) {
  1825.         return FALSE;
  1826.     }
  1827.     if (!fwritelong(dir->new.size,f)) {
  1828.         return FALSE;
  1829.     }
  1830.     if (!fwritelong(dir->new.where,f)) {
  1831.         return FALSE;
  1832.     }    
  1833.   }
  1834.   return TRUE;
  1835. }
  1836.  
  1837. /* write a four byte number <hihi lohi hilo lolo> */
  1838. static int fwritelong(buf,f)
  1839.   long buf;
  1840.   FILE *f;
  1841. {
  1842.   unsigned char b[4];
  1843.  
  1844.   b[0] = (unsigned char)(((unsigned long)buf & 0xFF000000L) >> 24);
  1845.   b[1] = (unsigned char)(((unsigned long)buf & 0x00FF0000L) >> 16);
  1846.   b[2] = (unsigned char)(((unsigned long)buf & 0x0000FF00L) >> 8);
  1847.   b[3] = (unsigned char) ((unsigned long)buf & 0x000000FFL);
  1848.   if (fwrite((char *)b,1,4,f) != 4) {
  1849.     return FALSE;
  1850.   }
  1851.   return TRUE;
  1852. }
  1853.  
  1854. /* write a two byte number <hi lo> */
  1855. #ifdef ANSI
  1856. static int fwriteshort(unsigned short buf, FILE *f)
  1857. #else
  1858. static int fwriteshort(buf,f)
  1859.   unsigned short buf;
  1860.   FILE *f;
  1861. #endif /* ANSI */
  1862. {
  1863.   unsigned char b[2];
  1864.  
  1865.   b[0] = (unsigned char)(((unsigned long)buf & 0x0000FF00L) >> 8);
  1866.   b[1] = (unsigned char) ((unsigned long)buf & 0x000000FFL);
  1867.   if (fwrite((char *)b,1,2,f) != 2) {
  1868.     return FALSE;
  1869.   }
  1870.   return TRUE;
  1871. }
  1872.  
  1873.